package org.uninova.mobis.servlets;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import net.sf.json.JSONObject;

import org.uninova.mobis.api.interfaces.swedish.ResRobotJourneyPlannerInterface;
import org.uninova.mobis.pojos.Coordinate;
import org.uninova.mobis.pojos.ResRobotSegment;
import org.uninova.mobis.pojos.Segment;
import org.uninova.mobis.pojos.Segments;
import org.uninova.mobis.utils.GISUtilsImpl;

import com.google.gson.Gson;

/**
 * Servlet implementation class GetResRobotRoutesJSONServlet
 */
@WebServlet("/GetResRobotRoutesJSON")
public class GetResRobotRoutesJSONServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public GetResRobotRoutesJSONServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		processRequest(request, response) ;
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		processRequest(request, response) ;
	}
	
	/**
	 * This servlet calculates the possible routes between origin and destination, at a given time and date, in order to provide different options in terms of public transports.
	 * 
	 * @param origin		The WSG84 coordinate of the origin location for calculating possible ResRobot routes
	 * @param destination	The WSG84 coordinate of the destination location for calculating possible ResRobot routes
	 * @param waypoints		The WSG84 coordinates for waypoints between origin and destination, separated by (,)double exclamation marks(!!)
	 * @param time			The ISO8601 formatted time and date for the beginning of the trip
	 * 
	 * @return				The Segment object contains one route composed by several segments. Each Segment object has its ID, the destination and origin WSG84 coordinates and the 
	 * 						different possible ways (routes) that connect both points via public transports. Because a route may have several waypoints, several Segment objects are considered, by putting them into an array
	 */
	protected void processRequest(HttpServletRequest request, HttpServletResponse response) {
		String origin = request.getParameter("origin") ;
		String destination = request.getParameter("destination") ;
		String waypoints = request.getParameter("waypoints") ;
		
		// DEPARTURE TIME
		String time = request.getParameter("time") ;
		if (time.contains("%20"))
			time = time.replace("%20", " ") ;
		
		//String carSharing = request.getParameter("carSharing") ;
		
		GISUtilsImpl gisUtils = new GISUtilsImpl() ;
		
		Double originLat, originLng, destLat, destLng ;
		
		Coordinate originCoord = gisUtils.getCoordinateFromString(origin) ;
		originLat = originCoord.lat ;
		originLng = originCoord.lng ;
		
		Coordinate destCoord = gisUtils.getCoordinateFromString(destination) ;
		destLat = destCoord.lat ;
		destLng = destCoord.lng ;
		
		ArrayList<Double> lats = new ArrayList<Double>() ;
		ArrayList<Double> lngs = new ArrayList<Double>() ;
		
		ResRobotJourneyPlannerInterface resRobotInterface = new ResRobotJourneyPlannerInterface() ;
		Coordinate fromCoord, toCoord ;
		JSONObject resObject ;
		HashMap<String, ArrayList<ResRobotSegment>> segmentMap ;
		String resp = "" ;
		
		HttpSession session = request.getSession() ;
		
		String result = "" ;
		
		lats.add(originLat) ;
		lngs.add(originLng) ;
		
		// HANDLE WAYPOINTS, IF ANY
		if (waypoints != null && !waypoints.equals("") && !waypoints.equals("null")) {
			String[] points = null ;
			if (waypoints.contains("!!"))
				points = waypoints.split("!!") ;
			else {
				points = new String[1] ;
				points[0] = waypoints ;
			}
			
			if (points.length > 0) {
				String point ;
				Coordinate coord ;
				
				for (int i = 0; i < points.length; i++) {
					point = points[i] ;
					coord = gisUtils.getCoordinateFromString(point) ;
					
					lats.add(coord.lat) ;
					lngs.add(coord.lng) ;
				}
			}
		}
		
		lats.add(destLat) ;
		lngs.add(destLng) ;
		
		Gson gson = new Gson() ;
		
		//resp += "{\"segments\":[" ;
		ArrayList<Segment> segments = new ArrayList<Segment>() ;
		Segment seg ;
		ArrayList<ResRobotSegment> first ;
		for (int i = 0; i < lats.size() - 1; i++) {
			
			originLat = lats.get(i) ;
			originLng = lngs.get(i) ;
			
			destLat = lats.get(i + 1) ;
			destLng = lngs.get(i + 1) ;
			
			fromCoord = new Coordinate(originLat, originLng) ;
			toCoord = new Coordinate(destLat, destLng) ;
			
			// GET THE DIFFERENT ROUTES AVAILABLE USING PUBLIC TRANSPORTS 
			
			result = resRobotInterface.search("coords", fromCoord, toCoord, null, null, time, false, 1, null) ;
			resObject = JSONObject.fromObject(result) ;
			
			// SAVE THE RESULTING ROUTES INTO A SESSION VARIABLE, SO IT CAN BE USED BY SERVLET 'GetDirectionsResRobot'
			if (session.getAttribute("resRobotResult") != null) {
				result = session.getAttribute("resRobotResult") + "!!" + result ;
			}
					
			session.setAttribute("resRobotResult", result) ;
			
			segmentMap = resRobotInterface.parseAllSegments(resObject) ;
			
			first = segmentMap.get(segmentMap.keySet().iterator().next()) ;
			
			seg = new Segment() ;
			seg.setDeparture(first.get(0)) ;
			seg.setArrival(first.get(first.size() - 1)) ;
			
			
			seg.setSegment(i) ;
			seg.setOptions(segmentMap) ;
			//resp += "{\"segment\":" + i + ",\"options\":\"" ;
			
			//JSONObject jsonMap = JSONObject.fromObject(segmentMap) ;
			//resp += jsonMap.toString() ;
			//resp += "}," ;
			segments.add(seg) ;
		}
		//resp = resp.substring(0, resp.lastIndexOf(",")) ;
		//resp += "]}" ;
		Segments segs = new Segments() ;
		segs.setSegments(segments) ;
		resp = gson.toJson(segs) ;
		try {
			response.setContentType("text/html;charset=UTF-8");
			PrintWriter out = response.getWriter() ;
			out.println(resp) ;
			out.close() ;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}
